/**
    webpack.config.js webpack的配置文件
        作用：指示 webpack 干那些活（当你运行 webpack 指令时，会加载里面的配置）
        所有构件工具都是基于 nodejs 平台运行的~模块化默认采用 commonjs

    loader： 1、下载    2、使用（配置loader）
    plugins： 1、下载    2、引用    3、使用（配置plugins）
*/

// resolve 用来拼接绝对路径的方法
const { resolve } = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin');
// 提取css为单独文件，而并非打包到html中去
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
// 压缩css的插件
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');

// html-webpack-plugin
// new HtmlWebpackPlugin()   功能：默认会创建一个空的html文件，不会自动引入打包输出的所有资源（js/css）
const htmlWebpackPlugin = new HtmlWebpackPlugin({
    // 复制 './src/index.html' 文件，并自动引入打包输出的所有资源（js/css）
    template: './src/index.html',
    // 重命名
    filename: 'index.html',
    minify:{
        // 移除空格
        collapseWhitespace: true,
        // 移除注释
        removeComments:true,
    }
});

const miniCssExtractPlugin = new MiniCssExtractPlugin({
    // 对输出的css文件进行重命名
    filename: 'css/built.css'
});

const optimizeCssAssetsPlugin = new OptimizeCssAssetsPlugin();

// 对 node 环境的配置
// process.env.NODE_ENV = 'development';

module.exports = {
    // webpack 配置
    // 入口起点
    entry: './src/js/index.js',
    // 输出
    output: {
        // 输出文件名
        filename: 'js/build.js',
        // __dirname 是nodejs的变量，代表当前文件的目录的绝对路径,相当于【./】
        // resolve(__dirname,'build') 方法就相当于将这两个目录拼接起来
        path: resolve(__dirname, 'build')
    },
    // loader 配置
    module: {
        // npm i style-loader css-loader less-loader url-loader file-loader mini-css-extract-plugin postcss-loader postcss-preset-env -D
        rules: [
            // 处理 css 文件打包的加载器，加载器的顺序不能乱写
            // 加载器是按照顺序调用（从后往前调用，css-loader->style-loader）
            // css
            {
                test: /\.css$/,
                use: [
                    // 'style-loader', // 创建style标签，将js中的样式资源插入进去，添加到head中生效
                    MiniCssExtractPlugin.loader,// 这个loader取代 style-loader .作用：提取js中的css成单独文件
                    'css-loader', // 将css文件变成 commonjs 模块加载到js中，里面内容是样式字符串
                    // 使用 postcss-loader 时需要下载两个loader ，分别是 postcss-loader postcss-preset-env
                    // 'postcss-loader' // 是处理兼css的部分兼容问题
                    {
                        loader:'postcss-loader',
                        options:{
                            ident:'postcss',
                            // postcss的插件，帮助postcss找到 package.json 中 browserslist 里面的配置，
                                // 通过配置加载指定的css兼容性样式
                                /*
                                    "browserslist":{
                                        // 这里的环境与下面的 mode配置 是无关的，需要单独设置
                                        // 开发环境--》设置node环境变量： process.env.NODE_ENV = 'development';
                                        "development":[
                                        "last 1 chrome version",
                                        "last 1 firefox version",
                                        "last 1 safari version"
                                        ],
                                        // 生产环境，默认是生产环境
                                        "production":[
                                        ">0.2%", //大于使用量为0.2%以上的大浏览器
                                        "not dead",// 不要已经死了的浏览器【停止更新】
                                        "not op_mini all"
                                        ]
                                    }
                                 */
                            plugins:()=>[require('postcss-preset-env')]
                        }
                    }
                ]
            },
            // 正常来讲，一个文件只能被一个loader处理。当一个文件要被多个loader处理时，那么一定要指定loader执行的先后顺序：
            //  先执行eslint 再执行babel
            // js eslint
            {
                /*
                    js 语法检查： eslint-loader eslint
                        注意： 只检查自己写的源代码，第三方的库是不用检查的
                        设置检查规则：
                            package.json 中 eslintConfig 中设置（集成一个默认的检查风格）：
                                            "eslintConfig": {
                                                "extends": "airbnb-base"
                                            }
                            aribnb --> eslint-config-airbnb-base eslint eslint-plugin-import
                    安装相关的依赖：  npm -i eslint-loader eslint-config-airbnb-base eslint eslint-plugin-import -D


                */
                test:/\.js$/,
                // 不对 node_modules 文件夹中的语法进行检查
                exclude:/node_modules/,
                // 优先执行的意思
                enforce:'pre',
                loader:'eslint-loader',
                options:{
                    // 自动修改eslint的相关格式
                    fix:true
                }
            },
            // js 兼容
            {
                /*
                    js兼容性处理： babel-loader
                        1、比如讲es6的语法转化为根底版本的语法【示例：箭头函数转化为普通函数】
                            只能转化为基本语法，但是 Promise 还是无法进行转换
                        2、第一种方式 ：
                            所以我们需要进行一个全部的js兼容性处理 
                            --> @babel/polyfill  
                            --> 只需要在js文件中进行引用就行了 
                            --> import '@babel/polyfill'; 
                            --> 这样字会产生很大的一个js
                        3、第二种方式 ：
                            --> 此时我们需要按需引入，此时就需要一个 core-js 依赖了
                    下载相关的依赖： npm i babel-loader @babel/core @babel/preset-env @babel/polyfill core-js -D
                */
                test: /\.js$/,
                exclude:/node_modules/,
                loader:'babel-loader',
                options:{
                    // 预设： 指示babel做怎么样的兼容性处理
                    // presets:['@babel/preset-env'],   // 第一种方式，直接解决全部兼容问题
                    presets:[                           // 第二种方式，按需解决兼容问题
                        [
                            '@babel/preset-env',
                            {
                                // 按需加载
                                useBuiltIns:'usage',
                                // 指定 core-js 版本
                                corejs:{
                                    version:3
                                },
                                // 指定具体的兼容到那个版本的浏览器
                                targets:{
                                    chrome:'60',
                                    firefox:'60',
                                    ie:'9',
                                    safari:'10',
                                    edge:'17',
                                }
                            }
                        ]
                    ]
                }
            },
            // 图片
            // 处理图片相关的加载器， limit 是用来指定图片大小的，单位是 byte ，
            // 只有小于 limit 大小的图片，才会被转换为 base64 图片
            // 这个图片loader需要下载两个loader,因为 url-loader 依赖于 file-loader
            {
                // test: /\.jpg|png|gif|bmp|ttf|eot|svg|woff|woff2/,
                test: /\.jpg|png|gif/,
                // 注：【当loader只有一个时可以使用方式二的模式写，如果有多个并且有不同的参数可以使用方式一】
                // 方式一配置
                // use: ['url-loader?limit=8192&esModule=false&name=[hash:10].[ext]']
                // 方式二配置
                loader: 'url-loader',
                options: {
                    // 图片大小小于8kb，就会被base64处理
                    // 优点：减少请求数量【减轻服务器压力】
                    // 缺点：图片体积会更大【文件请求速度更慢】
                    limit: 8 * 1024,
                    // 问题：因为url-loader默认使用es6模块化解析，而html-loader引入图片是commonjs
                    // img 标签进行解析时就会出现 src="[object Module]"
                    // 解决方案：关闭 url-loader 的es6模块化,使用commonjs来进行解析
                    esModule:false,
                    // 给图片进行重命名
                    // [hash:10] 取图片的hash值的前10位
                    // [ext] 取文件原来扩展名
                    name: '[hash:10].[ext]'
                }
            },
            // html
            {
                test: /\.html$/,
                loader: 'html-loader' // 处理html文件中的img图片，【负责引入img,从而能被url-loader进行处理】
            },
            // 处理其他文件
            {
                exclude:/\.(js|css|less|html|jpg|png|gif)/,
                loader:'file-loader',
                options:{
                    outputPath:'media'
                }
            }
        ]
    },
    plugins: [
        // 详细的plugins的配置
        htmlWebpackPlugin,miniCssExtractPlugin,optimizeCssAssetsPlugin
    ],
    // mode: 'development', // 开发模式
    mode: 'production', // 生产模式  会自动压缩js代码

    // 开发服务器 devServer ： 用来自动化【自动编译，自动打开浏览器，自动刷新】
    // 只会在内存中编译打包，不会有任何输出
    // 启动devServer指令： npx webpack-dev-server 
    devServer:{
        contentBase:resolve(__dirname,'build'),
        // 启动gzip压缩
        compress:true,
        // 端口号
        port:3000,
        // 是否自动打开默认浏览器
        open:false,
    },

}